/**
 * Copyright 2008 Mathias Doenitz, http://lis.to/
 *
 * This file is part of the lis.to java desktop client. The lis.to java desktop client is free software: you can
 * redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * The lis.to java desktop client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with the lis.to java desktop client.
 * If not, see http://www.gnu.org/licenses/
 */

package listo.utils.guice;

import com.google.inject.Key;
import listo.utils.logging.Log4JLog;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.ConcurrentMap;

public class CustomScopes {

    private CustomScopes() {}

    public static final ManualScope MANUAL = new ManualScope();
    public static final CalendarDayScope CALENDAR_DAY = new CalendarDayScope();

    /**
     * A guice scope bound to an identifier that is set via the ManuallyScoped
     * annotion. The scope can be "manually" reset by calling reset().
     */
    public static class ManualScope extends AbstractMapContextScope<String> {

        protected ManualScope() {
            super(new Log4JLog(), String.class, "CustomScopes.MANUAL");
        }

        @SuppressWarnings({"unchecked"})
        public String get(Key<?> key) {
            Class type = (Class) key.getTypeLiteral().getType();
            ManuallyScoped anno = (ManuallyScoped) type.getAnnotation(ManuallyScoped.class);
            return anno.value();
        }

        public void reset(String domain) {
            log.debug("scope %s: resetting domain %s", this.toString(), domain);
            ConcurrentMap contextMap = map.get(domain);
            if (contextMap == null) {
                throw new IllegalArgumentException(String.format("Non-existent scope name '%s'", domain));
            }
            contextMap.clear();
        }
    }

    /**
     * A simple scope that is bound to the calendar day.
     */
    public static class CalendarDayScope extends AbstractMapContextScope<Integer> {

        protected CalendarDayScope() {
            super(new Log4JLog(), Integer.class, "CustomScopes.CALENDAR_DAY");
        }

        @SuppressWarnings({"unchecked"})
        public Integer get(Key<?> key) {
            GregorianCalendar cal = new GregorianCalendar();
            return (cal.get(Calendar.YEAR) * 1000) + cal.get(Calendar.DAY_OF_YEAR);
        }
    }

}